home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGBLER
/
ASMCODE2.LZH
/
SQ_RT.ASM
< prev
next >
Wrap
Assembly Source File
|
1983-10-15
|
14KB
|
448 lines
;SQR_T.ASM 10-14-83
;
;PROGRAM TO TAKE KEYBOARD INPUT AND CALCULATE THE SQUARE
;ROOT USING THE SQ ROOT ROUTINE, THEN DISPLAY THE RESULT
;
EXTRN ASCII_BIN:FAR ;EXTERNAL SUBROUTINE
EXTRN BIN_ASCII:FAR ;EXTERNAL SUBROUTINE
EXTRN DEC_ADJ:FAR ;EXTERNAL SUBROUTINE
EXTRN PUT_DEC:FAR
;---------------------------------------
STACK SEGMENT PARA STACK 'STACK'
DB 256 DUP(0)
STACK ENDS
;----------------------------------------
DATA SEGMENT PARA 'DATA'
ESC EQU 27 ;ESC USED TO RETURN TO DOS
END_SYM EQU '\' ;SYMBOL AT END OF STRING
SC_TITLE DB 'INTEGER SQUARE ROOT ROUTINE\'
TYPE_NUM DB 'FOR A POSITIVE NUMBER FROM 0 TO 32767\'
INPUT_NUM DB 'INPUT TEST NUMBER \'
COL_HEADER DB 'TEST NUMBER SQ ROOT\'
UNDERLINE DB '----------- --------\'
ERR_MSG1 DB 'NOT VALID NUMBER - REDO \'
ERR_MSG2 DB 'NUMBER TOO LARGE - REDO \'
ERR_MSG3 DB 'NEGATIVE NUMBER - REDO\'
BLANKS DB ' \' ;25 BLANKS
TEST_STRING DB 10 DUP(0)
TEST_NUMBER DW 0 ;THE TEST_STRING CONVERTED TO A NUMBER
CHAR_COUNT DW 0 ;NO. OF CHARS IN A STRING - CX IN BIOS CALL
SQ_ROOT_VALUE DW 0 ;CALUCLATED SQ ROOT VALUE
SQ_ROOT_STRING DB ' \' ;STRING TO PUT CAL VALUE IN FOR DISP
OFFSET_VALUE DW 0
INPUT_LARGE DW 0 ;STATUS PASSING INDICATOR
INPUT_STATUS DW 0 ;STATUS PASSING INDICATOR
DEC_POINT DW 0
test1 db 'test4\'
test2 db 'test2\'
test3 db 'test3\'
TEST_NUM_CNT DB 10 DUP (0) ;STRING TO USE IN FINDING WHERE DECIMAL WAS
TEST_NUMBER_SIZE DW 0 ;INDICATOR IF TEST_NUMBER <1 OR >1
data ends
;----------------------------------------
CODE SEGMENT PARA PUBLIC 'CODE'
START PROC FAR
;
;STANDARD PROGRAM PROLOGUE
;
ASSUME CS:CODE
PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
ASSUME DS:DATA
CALL CLEAR_THE_SCREEN
;PUT STRING OF SCREEN
;IF COLOR GRAPHICS MAKE SURE IS MODE 2
MOV AH,15
INT 10H
CMP AL,7 ;IS IT MONOCHROME?
JE SCREEN_MODE_OK ;YES
CMP AL,2 ;NOT MONO, IS MODE 2?
JE SCREEN_MODE_OK ;YES
MOV AH,0 ;NOT MODE 2 SO MAKE IT
MOV AL,2 ; MODE 2
INT 10H
SCREEN_MODE_OK:
;SC_TITLE
MOV AH,2 ;CALL TO SET CURSOR POSITION
MOV DX,0112H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX,OFFSET SC_TITLE ;PUT SC_TITLE ADDRESS IN BX
MOV OFFSET_VALUE,BX ;PUT ADDRESS IN VARIABLE
CALL DISPLAY
;TYPE_NUM
MOV AH,2
MOV DX,0210H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX,OFFSET TYPE_NUM
MOV OFFSET_VALUE,BX ;PUT ADDRESS IN VARIABLE
CALL DISPLAY
;INPUT_NUM
MOV AH,2
MOV DX,0310H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX,OFFSET INPUT_NUM
MOV OFFSET_VALUE,BX
CALL DISPLAY
;COL_HEADER
MOV AH,2 ;CALL TO SET CURSOR POSITION
MOV DX,0510H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX, OFFSET COL_HEADER
MOV OFFSET_VALUE,BX ;PUT ADDRESS IN VARIABLE
CALL DISPLAY
;UNDERLINE
MOV AH,2
MOV DX,0610H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX,OFFSET UNDERLINE
MOV OFFSET_VALUE,BX
CALL DISPLAY
;POSITION CURSOR FOR KEYBOARD INPUT
INPUT:
;CLEAR_INPUT_AREA
MOV AH,2
MOV DH,3
MOV DL,25H
MOV BH,0
INT 10H
MOV BH,0
MOV CX,30 ;blank 30 spaces
MOV AH,10 ;WRITE CHAR AT CURSOR LOCATION
MOV AL,' ' ;BLANK
INT 10H
;clear test_string
LEA SI,TEST_STRING
mov cx,10 ;TEST STRING IS 10 CHAR LONG
next_char:
MOV BYTE PTR [SI],' '
inc SI
dec cx
cmp cx,0
JA next_char
;SCROLL PART OF SCREEN DOWN TOO BET READY FOR NEXT INPUT
MOV AH,7 ;SCROLL ACTIVE PAGE DOWN
MOV AL,1 ;NUMBER OF LINES
MOV CH,7 ;UPPER LINE TO SCROLL
MOV CL,0 ;LEFT COLUMN OF SCROLL
MOV DH,23 ;LOWER LINE OF SCROLL
MOV DL,79 ;RIGHT COLUMN OF SCROLL
MOV BH,0FH ;ATTRIBUTE OF BLANK LINE
INT 10H ;DO IT
MOV INPUT_LARGE,0 ;SET TO ZERO AT START-UNDER 65384
MOV INPUT_STATUS,0 ;SET TO ZERO AT START-NUMBERS
MOV AH,2
MOV DX,0325H ;CURSOR POSITION
MOV BH,0
INT 10H
CALL READ_KEYS
;PUT THE TEST_NUMBER UNDER THE TEST NUMBER COLUMN HEADING
MOV AH,2
MOV DX,0711H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX,OFFSET TEST_STRING
MOV CX,10
PUT_TEST_NUMBER:
MOV AL,[BX] ;PUT STRING CHAR IN AX
MOV AH,14 ;FUNCTION CODE FOR WRITE AND ADVANCE CURSOR
INT 10H
INC BX ;NEXT CHARACTER IN STRING
LOOP PUT_TEST_NUMBER ;PUT ALL OF STRING + BLANKS
;PREPAIR TO CALL ASCII_BIN ROUTINE
;PUT STARTING ADDRESS OF STRING IN BX
;PUT CHARACTER COUNT IN CX
MOV BX,OFFSET TEST_STRING
MOV CX,CHAR_COUNT
CALL ASCII_BIN ;CONVERT STRING TO NUMBER
JC CARRY_SET ;GO CHECK WHY
MOV TEST_NUMBER,AX ;SAVE TEST NUMBER
MOV DEC_POINT,DX ;SAVE DECIMAL POINT
CMP AX,0 ;CHECK FOR NEGATIVE
JGE NUM_OK ;NUMBER IS GOOD-GO DO SQ ROOT
MOV AH,2
MOV DX,0730H ;CURSOR POSITION
INT 10H
MOV BX,OFFSET ERR_MSG3 ;NEGITIVE NUMBER
MOV OFFSET_VALUE,BX
CALL DISPLAY
JMP INPUT ;NEXT KEYBOARD INPUT
BAD_CHAR:
MOV AH,2
MOV DX,0730H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX,OFFSET ERR_MSG1 ;NOT VALID INPUT
MOV OFFSET_VALUE,BX
CALL DISPLAY
JMP INPUT ;GO GET NEXT KEYBOARD INPUT
CARRY_SET:
cmp di,0ffh ;check for bad character
jne bad_char
MOV AH,2
MOV DX,0730H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX,OFFSET ERR_MSG2
MOV OFFSET_VALUE,BX
CALL DISPLAY
JMP INPUT ;NOT VALID, GO GET NEW INPUT
NUM_OK:
;ADJUST NUMBER FOR SQUART ROOT ROUTING BY MAKING NUMBER AS LARGE AS
;POSSIBLE, BUT LESS THEN 32768, BY MULTIPLYING BY 10 AND CHANGINE
;DECIMAL POINT TO MATCH.
; CALL DEC_ADJ WITH AX = NUMBER - 16 BIT SIGNED
; CX = NUMBER OF CHARACTERS TO RIGHT OF DECIMAL POINT
;RETURN WITH AX = NUMBER AND CX = NUMBER OF CHARACTERS TO RIGHT
;OF DECIMAL POINT THAT TOGETHER = OLD NUMBER
; NOTE CX WILL BE A EVEN NUMBER
MOV AX,TEST_NUMBER
MOV CX,DEC_POINT
CALL DEC_ADJ
MOV TEST_NUMBER,AX
;NOW READY TO CALCULATE SQUARE ROOT. AX IS TO CONTAIN THE TEST
;NUMBER WHEN THE SQ_ROOT ROUTINE IS CALLED AND AX WILL CONTAIN
;THE CALCULATED SQ ROOT ON RET.
MOV AX,CX ;PUT DEC POINT IN AX FOR DIVIDE
CWD
MOV BX,2
DIV BX
MOV DEC_POINT,AX ;STORE SQ ROOT OF DEC POINT
MOV AX,TEST_NUMBER ;PUT NUMBER IN AX
CALL SQ_ROOT
MOV SQ_ROOT_VALUE,AX ;SAVE THE CALCULATED SQ ROOT VALUE
;CONVERT THE SQ_ROOT VALUE TO ASCII STRING AND PUT UNDER THE
;SQ ROOT HEADING
;CONVERT THE NUMBER TO A ASCII STRING
MOV BX,OFFSET SQ_ROOT_STRING ;PLACE TO PUT RESULT
CALL BIN_ASCII
;ON RETURN BX HOLDS ADDRESS OF THE STRING AND CX THE COUNT
;POSITION DECIMAL POINT IN SQ ROOT STRING
; CALL PUT_DEC WITH
; AX = 10 SIZE OF STRING
; BX = OFFSET OF ASCII STRING
; CX = NUMBER OF CHARACTERS IN STRING
; DX = NUMBER OF CHARACTERS TO RIGHT OF DECIMAL
;RETURN IS WITH DECIMAL IN STRING AT BX
MOV AX,10
MOV DX,DEC_POINT
CALL PUT_DEC
;SQ_ROOT_STRING NOW CONTAINS THE ANSWER READY FOR DISPLAY
MOV AH,2
MOV DX,0728H ;CURSOR POSITION
MOV BH,0
INT 10H
MOV BX,OFFSET SQ_ROOT_STRING
MOV OFFSET_VALUE,BX
CALL DISPLAY
JMP INPUT ;READY FOR AN OTHER KEYBOARD INPUT
START ENDP
;------------------------------------------
CLEAR_THE_SCREEN PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
STI ;ENABLE INTERRUPTS
MOV AH,0 ;SELECT 80X25, B/W, ALPHANUMERIC
INT 10H
MOV AH,6 ;CLEAR THE SCREEN WITH THE SCROLL
MOV AL,0 ; UP OPTION
MOV CX,0
MOV DH,24
MOV DL,79
MOV BH,7
INT 10H
POP DX
POP CX
POP BX
POP AX
RET ;RETURN TO CALLER
CLEAR_THE_SCREEN ENDP
;------------------------------------------
DISPLAY PROC NEAR
;GET THE CHARACTER COUNT
MOV CHAR_COUNT,0 ;SET TO 0 FOR THIS STRING
MOV BX,OFFSET_VALUE ;GET OFFSET OF STRING IN BX
XOR AX,AX
LOOP_COUNT:
MOV AL,[BX] ;PUT STRING CHAR IN AL
CMP AL,END_SYM ;IS THIS LAST SYMBOL IN STRING?
JE DISP1
INC BX ;ADDRESS OF NEXT CHARACTER IN STRING
ADD CHAR_COUNT,1 ;COUNT OF CHARACTERS IN STRING
JMP LOOP_COUNT ;DO UNTIL END_SYM ENCOUNTERED
;PUT THE STRING ON THE SCREEN
DISP1: MOV BX,OFFSET_VALUE ;GET OFFSET OF STRING IN BX
MOV CX,CHAR_COUNT ;NO. OF CHARACTERS IN STRING
DISP2: MOV AL,[BX] ;GET NEXT CHARACTER
CALL DISPCHAR
INC BX ;POINT TO NEXT CHARACTER
LOOP DISP2 ;DO IT CX TIMES
RET
DISPLAY ENDP
;---------------------------------------------------------
DISPCHAR PROC NEAR
PUSH BX
MOV BX,0 ;SELECT DISPLAY PAGE 0
MOV AH,14 ;FUNCTION CODE FOR 'WRITE'
INT 10H ;CALL BIOS
POP BX
RET
DISPCHAR ENDP
;--------------------------------------------------------
READ_KEYS PROC NEAR
PUSH AX
PUSH DI
STI ;ENABLE INTERRUPTS
MOV AH,15 ;READ DISPLAY PAGE NUMBER INTO BX
INT 10H
MOV DI,0 ;SET KEY COUNT TO ZERO
MOV CX,5 ;UP TO 5 KEY STROKES
GET_KEY:
MOV AH,0 ;READ NEXT KEY
INT 16H
CMP AL,ESC ;IS IT ESC?
JE GO_EXIT ;RETURN TO DOS IN TWO STEPS(JE SHORT-LABEL ONLY)
CMP AL,0DH ;IS IT A CARRIAGE RETURN?
JE SAVE_CNT ;IF IT WAS A CARRIAGE RETURN THEN GO TO NEXT STEP
MOV TEST_STRING[DI],AL ;STORE THE KEY INPUT
INC DI ;INCREASE THE KEY COUNT
MOV AH,14 ;DISPLAY THE CHARACTER
PUSH DI ;SAVE REGISTER
INT 10H
POP DI
LOOP GET_KEY ;GO GET NEXT KEY
SAVE_CNT:
MOV CX,DI ;PUT FINAL KEY COUNT IN CX
MOV CHAR_COUNT,CX ;STORE NO OF CHARS IN STRING
LEA BX,TEST_STRING ;BUFFER ADDRESS IN BX
POP DI
POP AX
RET ;RETURN TO CALLER
GO_EXIT:
POP DI
POP AX
POP AX
JMP EXIT ;RETURN TO DOS
READ_KEYS ENDP
;----------------------------------------------------------
;-----------------------------------------------------------------
;
;-------------------------------------------------------------
;----------------------------------------------------------------
;INTEGER SQUARE ROOT
; CALL WITH AX = ARGUMENT
; RETURN AX = SQUARE ROOT
;
SQ_ROOT PROC
SQRT:
PUSH BX
PUSH CX
PUSH DX
MOV DX,AX ;ARGUMENT INTO DX
MOV CX,8 ;NUMBER OF ITERATIONS
XOR BX,BX ;CLEAR THE REMAINDER
MOV AX,BX ;CLEAR TRIAL VALUE AND FINAL RESULT STORE
SQRT1:
SHL BX,1 ;DOUBLE PARTIAL RESULT
INC BX ;GUESS NEXT BIT IS A 1
SHL DX,1 ;FETCH 2 NEW BITS
RCL AX,1 ; FROM ARGUMENT
SHL DX,1
RCL AX,1
SUB AX,BX ;DO A TRIAL SUBTRACTION
JNC SQRT2 ;GUESS WAS RIGHT
; APPEND A 1 BIT
ADD AX,BX ;GUESS WAS WRONG, PUT IT BACK
DEC BX ;AND CLEAN UP FOR NEXT PASS
LOOP SQRT1
JMP SQRT3 ;GO SCALE RESULT
SQRT2:
INC BX ;CONVERT xxxx01 to
;xxxx10, i.e. append a 1 bit
loop sqrt1
SQRT3:
SAR BX,1 ;DIVIDE BY 2 TO GET
;ACTUAL SQUARE ROOT
MOV AX,BX ;RETURN RESULT IN AX
POP DX
POP CX
POP BX
RET ;RETURN TO CALLER
SQ_ROOT ENDP
;--------------------------------------------------------------------
EXIT_TO_DOS PROC FAR
EXIT: RET ;RETURN TO DOS
EXIT_TO_DOS ENDP
;----------------------------------------------------------
CODE ENDS
END START